package com.itheima.tanhua.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.db.PageResult;
import com.alibaba.nacos.common.utils.Objects;
import com.itheima.autoconfig.template.OssTemplate;
import com.itheima.tanhua.api.db.UserServiceApi;
import com.itheima.tanhua.api.mongo.CommentApi;
import com.itheima.tanhua.api.mongo.MovementApi;
import com.itheima.tanhua.enums.CommentType;
import com.itheima.tanhua.exception.ConsumerException;
import com.itheima.tanhua.interceptor.userHolder;
import com.itheima.tanhua.pojo.db.UserInfo;
import com.itheima.tanhua.pojo.mongo.Comment;
import com.itheima.tanhua.pojo.mongo.Movement;
import com.itheima.tanhua.until.mongo.Constants;
import com.itheima.tanhua.vo.mongo.MovementsVo;
import com.itheima.tanhua.vo.mongo.pageResult;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 芝士雪豹
 * @create 2022/9/24/20:19
 */
@Service
public class MovementService {
    @Autowired
    private OssTemplate ossTemplate;
    @DubboReference
    private MovementApi movementApi;
    @DubboReference
    private UserServiceApi userServiceApi;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @DubboReference
    private CommentApi commentApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplates;

    /**
     * 上传动态
     *
     * @param movement
     * @param imageContent
     * @throws IOException
     */
    public void publish(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断上传文件是否存在
        if (StringUtils.isNotEmpty(movement.getTextContent())) {
            throw new ConsumerException("上传文件为空");
        }
        //获取当前用户id
        Long id = userHolder.getId();
        //将文件上传到阿里云
        List<String> list = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            //将文件上传到阿里云 获得请求地址
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            //存入临时集合
            list.add(upload);
        }
        //将当前数据存入 movement 动态详情表
        //当前动态发布人id
        movement.setUserId(id);
        //存入数据
        movement.setMedias(list);
        //调用api层,去做处理
        movementApi.publish(movement);
    }

    /**
     * 查询圈子 个人动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public pageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //调用api进行数据处理
        pageResult pr = movementApi.findByuserId(userId, page, pagesize);
        //获取items 对象信息
        List<Movement> items = (List<Movement>) pr.getItems();
        //非空判断
        if (items == null) {
            return pr;
        }
        //根据id获取userInfo对象
        UserInfo userInfo = userServiceApi.findById(userId);
        //临时集合,存储对象
        List<MovementsVo> list = new ArrayList<>();
        //循环数组
        for (Movement item : items) {
            MovementsVo init = MovementsVo.init(userInfo, item);
            list.add(init);
        }
        pr.setItems(list);
        return pr;
    }

    /**
     * 查询好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public pageResult findFriendMovement(Integer page, Integer pagesize) {
        //获取当前用户id
        Long userId = userHolder.getId();
        //调用APi查询当前用户好友发布的动态列表
        List<Movement> list = movementApi.findFriend(userId, page, pagesize);
        //判断列表是否为空
        //ObjectUtil.isNotNull();
        if (ObjectUtil.isNull(list)) {
            return new pageResult(1, 10, null);
        }
        //提取动态发布人的id列表
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //根据用户的id列表获取用户详情
        HashMap<Long, UserInfo> hashMap = new HashMap<>();
        for (Long id : userIds) {
            UserInfo userInfo = userServiceApi.findById(id);
            hashMap.put(userInfo.getId(), userInfo);
        }
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = hashMap.get(movement.getUserId());
            if (userInfo != null) {
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                //点赞状态bug  判断hashkey是否存在        toHexString()方法用于将long类型给定参数[value]的十六进制字符串表示为以16为基数的无符号long
                String Key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userHolder.getId();
                //如果存在 需要重新赋值=显示被点赞状态
                if (redisTemplates.opsForHash().hasKey(Key, hashKey)) {
                    vo.setHasLiked(1);
                }
                String loveKey = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String lovehashKey = Constants.MOVEMENT_LOVE_HASHKEY + userHolder.getId();
                //如果存在 需要重新赋值=显示被点赞状态
                if (redisTemplates.opsForHash().hasKey(loveKey, lovehashKey)) {
                    vo.setHasLoved(1);
                }
                vos.add(vo);
            }
        }
        //构建pageResult 返回
        return new pageResult(page, pagesize, vos);
    }

    //查询推荐动态
    public pageResult findRecommend(Integer page, Integer pagesize) {
        //- 从redis获取当前用户的推荐PID列表
        String redisKey = Constants.MOVEMENTS_RECOMMEND + userHolder.getId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //判断推荐数据是否存在   推荐数据 存在redis中
        List list = Collections.EMPTY_LIST;
        if (ObjectUtil.isNull(list)) {
            //  - 如果不存在，调用API随机获取10条动态数据
            list = movementApi.findRandomten(pagesize);
        } else {
            //  - 如果存在，调用API根据PID列表查询动态数据
            String[] values = redisValue.split(",");
            //判断查询的起始页 是否超过value长度
            if ((page - 1) * pagesize < values.length) {
                //根据 redis中的value值找到 分页 pid
                List<Long> pid = Arrays.stream(values).skip((page - 1) * pagesize)
                        .limit(pagesize).map(Long::valueOf).
                        collect(Collectors.toList());
                list = movementApi.findforPid(pid);
            }
        }
        // - 构造VO对象
        return new pageResult(page, pagesize, list);
    }

    //根据 id查询
    public MovementsVo findMovementById(String movementId) {
        //调用api id查询动态详情
        Movement movement = movementApi.findById(movementId);
        //判断详情是否有数据
        if (movement == null) {
            //封装vo对象
            UserInfo userInfo = userServiceApi.findById(movement.getUserId());
            return MovementsVo.init(userInfo, movement);
        }
        return null;
    }

    //动态点赞
    public Integer likeComment(String movementId) {
        //调用API查询用户是否点赞
        boolean flag = commentApi.findIsNotLike(movementId, userHolder.getId(), CommentType.LIKE);
        //如果已经点赞,抛出异常
        if (flag) {
            throw new ConsumerException("已点赞");
        }
        //调用api保存数据到mongodb
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userHolder.getId());
        comment.setCommentType(CommentType.LIKE.getType());
        Integer comments = commentApi.saveComments(comment);
        //拼接redis的key,将用户的点赞状态存入 redis
        String Key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userHolder.getId();
        redisTemplates.opsForHash().put(Key, hashKey, "1");
        return comments;
    }

    //取消点赞
    public Integer dislikeComment(String movementId) {
        //调用APi查询用户是否取消点赞
        boolean flag = commentApi.findIsNotLike(movementId, userHolder.getId(), CommentType.LIKE);
        //如果true 就是取消点赞状态,返回异常
        if (!flag) {
            throw new ConsumerException("已取消点赞");
        }
        //调用api保存数据到mongodb    //通过这3条属性定位到唯一的数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userHolder.getId());
        Integer count = commentApi.remove(comment);

        //拼接redis的key,将用户的点赞状态存入 redis
        String Key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userHolder.getId();
        //删除点赞状态
        redisTemplates.opsForHash().delete(Key,hashKey);
        return count;
    }
    //喜欢
    public Integer loveComment(String movementId) {
        //调用API查询用户是否点赞
        boolean flag = commentApi.findIsNotLike(movementId, userHolder.getId(), CommentType.LOVE);
        //如果已经喜欢,抛出异常
        if (flag) {
            throw new ConsumerException("已添加喜欢");
        }
        //调用api保存数据到mongodb
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userHolder.getId());
        comment.setCommentType(CommentType.LOVE.getType());
        Integer comments = commentApi.saveComments(comment);
        //拼接redis的key,将用户的点赞状态存入 redis
        String Key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + userHolder.getId();
        redisTemplates.opsForHash().put(Key, hashKey, "1");
        return comments;
    }
    //取消喜欢
    public Integer unloveComment(String movementId) {
        //调用APi查询用户是否取消点赞
        boolean flag = commentApi.findIsNotLike(movementId, userHolder.getId(), CommentType.LOVE);
        //如果true 就是取消喜欢状态,返回异常
        if (!flag) {
            throw new ConsumerException("已取消喜欢");
        }
        //调用api保存数据到mongodb    //通过这3条属性定位到唯一的数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userHolder.getId());
        Integer count = commentApi.remove(comment);

        //拼接redis的key,将用户的点赞状态存入 redis
        String Key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + userHolder.getId();
        //删除喜欢状态
        redisTemplates.opsForHash().delete(Key,hashKey);
        return count;
    }
}
